package com.jason.rxjavatest.newtest;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import com.jason.rxjavatest.R;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func0;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * @author hezhiyong
 * @create 2018-03-30 15:36
 * @desc Creating Observables(Observable的创建操作符)，比如：Observable.create()、Observable.just()、Observable.from()等等；
 * Transforming Observables(Observable的转换操作符)，比如：observable.map()、observable.flatMap()、observable.buffer()等等；
 * Filtering Observables(Observable的过滤操作符)，比如：observable.filter()、observable.sample()、observable.take()等等；
 * Combining Observables(Observable的组合操作符)，比如：observable.join()、observable.merge()、observable.combineLatest()等等；
 * Error Handling Operators(Observable的错误处理操作符)，比如:observable.onErrorResumeNext()、observable.retry()等等；
 * Observable Utility Operators(Observable的功能性操作符)，比如：observable.subscribeOn()、observable.observeOn()、observable.delay()等等；
 * Conditional and Boolean Operators(Observable的条件操作符)，比如：observable.amb()、observable.contains()、observable.skipUntil()等等；
 * Mathematical and Aggregate Operators(Observable数学运算及聚合操作符)，比如：observable.count()、observable.reduce()、observable.concat()等等；
 * 其他如observable.toList()、observable.connect()、observable.publish()等等
 *
 *
 *
 **/
public class RxJavaNewTest001 extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = RxJavaNewTest001.class.getSimpleName();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxjava_new001);

        findViewById(R.id.bt_defer).setOnClickListener(this);
        findViewById(R.id.bt_interval).setOnClickListener(this);
        findViewById(R.id.bt_range).setOnClickListener(this);
        findViewById(R.id.bt_repeat).setOnClickListener(this);
        findViewById(R.id.bt_timer).setOnClickListener(this);
        findViewById(R.id.bt_next).setOnClickListener(this);


    }


    /**
     * defer操作符是直到有订阅者订阅时，才通过Observable的工厂方法创建Observable并执行，defer操作符能够保证Observable的状态是最新的
     */
    int i = 10;
    public void testDefer() {
        Observable justObservable = Observable.just(i);
        i = 12;
        Observable deferObservable = Observable.defer(new Func0<Observable<Object>>() {
            @Override
            public Observable<Object> call() {
                return Observable.just(i);
            }
        });
        i = 15;

        justObservable.subscribe(new Action1() {
            @Override
            public void call(Object o) {
                Log.e(TAG, "testDefer-----justObservable---->" + o.toString());
            }
        });

        deferObservable.subscribe(new Action1() {
            @Override
            public void call(Object o) {
                Log.e(TAG, "testDefer-----deferObservable---->" + o.toString());

            }
        });
        // just操作符是在创建Observable就进行了赋值操作，而defer是在订阅者订阅时才创建Observable，此时才进行真正的赋值操作
    }



    // 每隔一秒发送一次数据
    private void testInterval() {
        Observable.interval(1, TimeUnit.SECONDS)
                .subscribe(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {
                        Log.e(TAG, "testInterval--------->" + aLong.toString());
                    }
                });
    }

    /**
     * range操作符创建一个发射指定范围的整数序列的Observable，你可以指定范围的起始和长度。
     * - 它接受两个参数，一个是范围的起始值，一个是范围的数据的数目。如果你将第二个参数设为0，将导致Observable不发射任何数据（如果设置为负数，会抛异常）
     * - range默认不在任何特定的调度器上执行。有一个变体可以通过可选参数指定Scheduler。
     */
    private void testRange() {
        Observable.range(1,10)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.e(TAG, "testRange--------->" + integer.toString());
                    }
                });
    }

    /**
     * - repeat重复地发射数据。某些实现允许你重复的发射某个数据序列，还有一些允许你限制重复的次数。
     * - 它不是创建一个Observable，而是重复发射原始Observable的数据序列，这个序列或者是无限的，或者通过repeat(n)指定重复次数。
     * - repeat操作符默认在trampoline调度器上执行。有一个变体可以通过可选参数指定Scheduler。
     */
    private void testRepeat() {
        Observable.just(1).repeat(5)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.e(TAG, "testRepeat--------->" + integer.toString());
                    }
                });
    }

    /**
     * - timer操作符创建一个在给定的时间段之后返回一个特殊值的Observable
     * - timer返回一个Observable，它在延迟一段给定的时间后发射一个简单的数字0
     * - timer操作符默认在computation调度器上执行。有一个变体可以通过可选参数指定Scheduler
     */
    private void testTimer() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        String beginTime = sdf.format(new Date());
        Log.e(TAG, "testTimer---beginTime------>" + beginTime.toString());
        Observable.timer(2,TimeUnit.SECONDS)
                .subscribe(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {
                        Log.e(TAG, "testTimer--------->" + aLong.toString());
                        String endTime = sdf.format(new Date());
                        Log.e(TAG, "testTimer---endTime------>" + endTime.toString());
                    }
                });

    }









    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.bt_defer:
                testDefer();
                break;


            case R.id.bt_interval:
                testInterval();
                break;

            case R.id.bt_range:
                testRange();
                break;

            case R.id.bt_repeat:
                testRepeat();
                break;

            case R.id.bt_timer:
                testTimer();
                break;

            case R.id.bt_next:
                startActivity(new Intent(this, RxJavaNewTest002.class));
                break;
        }
    }
}
